package com.fqgj.sentry.biz.pc;

import com.fqgj.common.utils.CollectionUtils;
import com.fqgj.common.utils.JSONUtils;
import com.fqgj.common.utils.StringUtils;
import com.fqgj.sentry.biz.pc.vo.policy.ExecutorPolicyVo;
import com.fqgj.sentry.biz.pc.vo.policy.PolicyInfo;
import com.fqgj.sentry.common.cache.RequestLocalInfo;
import com.fqgj.sentry.common.exception.BizException;
import com.fqgj.sentry.common.exception.enums.ErrorCodeEnums;
import com.fqgj.sentry.controller.pc.request.policy.AddPolicyVo;
import com.fqgj.sentry.controller.pc.request.policy.PolicySortItemVo;
import com.fqgj.sentry.controller.pc.request.policy.PolicySortVo;
import com.fqgj.sentry.controller.pc.request.policy.UpdatePolicyVo;
import com.fqgj.sentry.policy.client.ExecuteResultService;
import com.fqgj.sentry.policy.client.PolicyService;
import com.fqgj.sentry.policy.client.RuleService;
import com.fqgj.sentry.policy.domain.policy.Policy;
import com.fqgj.sentry.policy.domain.policy.PolicyUpdate;
import com.fqgj.sentry.policy.engine.domain.Decision;
import com.fqgj.sentry.policy.engine.domain.WeightRange;
import com.fqgj.sentry.policy.entity.PcExecuteResultEntity;
import com.fqgj.sentry.policy.entity.PcPolicyEntity;
import com.fqgj.sentry.policy.entity.PcRuleEntity;
import com.fqgj.sentry.policy.enums.ActiveEnum;
import com.fqgj.sentry.policy.enums.ExecutorDefaultResultEnum;
import com.fqgj.sentry.policy.enums.PolicyMatchingTypeEnum;
import com.fqgj.sentry.policy.enums.PolicyTypeEnum;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * Created by ykpbean kangping.ying@yuntu-inc.com
 *
 * @description
 * @create 2017-07-29 下午3:35
 */

@Component
public class PolicyBusiness {

    @Autowired
    private PolicyService policyService;
    @Autowired
    private RuleService ruleService;

    @Autowired
    private ExecuteResultService executeResultService;

    public PolicyInfo findById(Long policyId) {
        PolicyInfo policyInfo = new PolicyInfo();
        PcPolicyEntity policyEntity = policyService.findById(policyId);
        BeanUtils.copyProperties(policyEntity, policyInfo);
        policyInfo.setPolicyId(policyEntity.getId());
        try {
            if (StringUtils.isNotEmpty(policyEntity.getWeightRange())) {
                List<Double> result = new ArrayList<>();
                List<WeightRange> weightRangeList = JSONUtils.json2list(policyEntity.getWeightRange(), WeightRange.class);
                result.add(weightRangeList.get(0).getStart());
                result.add(weightRangeList.get(weightRangeList.size() - 1).getStart());
                if (result.size() != 2) {
                    throw new BizException(ErrorCodeEnums.policy_weight_size_error, "策略权重配置有误");
                }
                policyInfo.setWeightRangeList(result);
            }

        } catch (Exception e) {
            throw new BizException(ErrorCodeEnums.json_transform_error);
        }
        return policyInfo;

    }

    /**
     * 策略新增
     *
     * @param addPolicyVo
     */
    public void add(AddPolicyVo addPolicyVo) {
        Policy policy = new Policy();
        BeanUtils.copyProperties(addPolicyVo, policy);
        policy.setTypeEnum(PolicyTypeEnum.getEnumByType(addPolicyVo.getType()))
                .setMatchingTypeEnum(PolicyMatchingTypeEnum.getEnumByType(addPolicyVo.getMatchingType()));

        //处理 权重问题
        List<Double> weightRange = addPolicyVo.getWeightRangeList();
        if (CollectionUtils.isNotEmpty(weightRange)) {
            policy.setWeightRange(getWeightRangeListStr(addPolicyVo.getPolicySetsId(), weightRange));
        }
        policyService.add(addPolicyVo.getExecutorId(), addPolicyVo.getPolicySetsId(), RequestLocalInfo.getCurrentMerchantId(), policy);
    }

    private WeightRange getWeightRange(Long policySetsId, ExecutorDefaultResultEnum executorResultEnum, Double firstRange, Double secondRange) {
        PcExecuteResultEntity executeResultEntity = executeResultService.selectExecuteResultListByResult(policySetsId, executorResultEnum);
        WeightRange range = new WeightRange();
        range.setStart(firstRange).setEnd(secondRange).setDecision(new Decision(
                Integer.valueOf(executeResultEntity.getId().toString()),
                executeResultEntity.getResult(),
                executeResultEntity.getLevel(), executeResultEntity.getResultType()));
        return range;
    }

    private String getWeightRangeListStr(Long policySetsId, List<Double> weightRange) {
        String weightRangeResult = "";
        if (CollectionUtils.isNotEmpty(weightRange)) {
            List<WeightRange> weightRangeList = new ArrayList<>();
            try {
                if (weightRange.size() != 2) {
                    throw new BizException(ErrorCodeEnums.policy_weight_size_error);
                }
                //划分最总结果
                Double firstRange = weightRange.get(0);
                Double secondRange = weightRange.get(1);
                if (firstRange >= secondRange) {
                    firstRange = weightRange.get(1);
                    secondRange = weightRange.get(0);
                }
                //查询所有执行者 结果
                if (firstRange == 0d) {
                    if (secondRange == 0d) {
                        weightRangeList.add(getWeightRange(policySetsId, ExecutorDefaultResultEnum.reject, 0d, 100d));
                    } else {
                        weightRangeList.add(getWeightRange(policySetsId, ExecutorDefaultResultEnum.review, 0d, secondRange));

                        weightRangeList.add(getWeightRange(policySetsId, ExecutorDefaultResultEnum.reject, secondRange, 100d));
                    }
                } else {
                    weightRangeList.add(getWeightRange(policySetsId, ExecutorDefaultResultEnum.pass, 0d, firstRange));

                    if (secondRange.toString().equals(firstRange.toString())) {
                        weightRangeList.add(getWeightRange(policySetsId, ExecutorDefaultResultEnum.reject, secondRange, 100d));
                    } else {
                        weightRangeList.add(getWeightRange(policySetsId, ExecutorDefaultResultEnum.review, firstRange, secondRange));
                        weightRangeList.add(getWeightRange(policySetsId, ExecutorDefaultResultEnum.reject, secondRange, 100d));
                    }
                }
                weightRangeResult = JSONUtils.obj2json(weightRangeList);
            } catch (Exception e) {
                throw new BizException(ErrorCodeEnums.json_transform_error);
            }
        }
        return weightRangeResult;

    }

    /**
     * 策略  更新
     *
     * @param policyVo
     */

    public void update(Long policyId, UpdatePolicyVo policyVo) {
        PcPolicyEntity policyEntity = policyService.findById(policyId);
        PolicyUpdate policy = new PolicyUpdate();
        BeanUtils.copyProperties(policyVo, policy);
        try {
            policy.setMatchingTypeEnum(PolicyMatchingTypeEnum.getEnumByType(policyVo.getMatchingType()));
            //权重匹配模块的修改
            //处理 权重问题
            List<Double> weightRange = policyVo.getWeightRangeList();
            if (CollectionUtils.isNotEmpty(weightRange)) {
                policy.setWeightRange(getWeightRangeListStr(policyEntity.getPolicySetsId(), weightRange));
            }
        } catch (Exception e) {
            throw new BizException(ErrorCodeEnums.json_transform_error);
        }
        policyService.update(policyId, policy);
    }

    /**
     * 策略删除
     *
     * @param policyId
     * @return
     */
    public Boolean delete(Long policyId) {
        return policyService.delete(RequestLocalInfo.getCurrentMerchantId(), policyId);
    }

    /**
     * 查询 规则使用情况
     *
     * @param executorId
     * @return
     */
    public List<ExecutorPolicyVo> queryPolicyList(Long executorId) {
        List<PcPolicyEntity> policyEntityList = policyService.selectPolicyByExecutorId(executorId);
        List<ExecutorPolicyVo> executorPolicyVoList = new ArrayList<>();
        for (PcPolicyEntity entity : policyEntityList) {
            ExecutorPolicyVo executorPolicyVo = new ExecutorPolicyVo()
                    .setPolicyId(entity.getId())
                    .setPolicyName(entity.getName())
                    .setType(entity.getType())
                    .setSort(entity.getSort())
                    .setCode(entity.getCode());
            //设置规则数量 和规则使用数
            List<PcRuleEntity> ruleEntityList = ruleService.findRuleListByPolicyId(entity.getId(), ActiveEnum.all.getType(), com.fqgj.sentry.policy.enums.RuleTypeEnum.custom.getType());
            Integer activeCount = 0;
            Integer ruleCount = ruleEntityList.size();
            for (PcRuleEntity ruleEntity : ruleEntityList) {
                if (ruleEntity.getIsActive().equals(ActiveEnum.active.getType())) {
                    activeCount++;
                }
            }
            executorPolicyVo.setActiveCount(activeCount);
            executorPolicyVo.setRuleCount(ruleCount);
            executorPolicyVoList.add(executorPolicyVo);
        }
        return executorPolicyVoList;
    }

    /**
     * 策略排序
     *
     * @param policySortVo
     * @return
     */
    public void updatePolicySort(PolicySortVo policySortVo) {
        List<PolicySortItemVo> policySortList = policySortVo.getPolicySortList();
        if (CollectionUtils.isEmpty(policySortList) || policySortList.size() == 1) {
            throw new BizException(ErrorCodeEnums.sort_error, "策略集合需大于1可排序~~");
        }
        for (PolicySortItemVo policyItem : policySortList) {
            policyService.updatePolicySort(policyItem.getPolicyId(), policyItem.getSort());
        }
    }

}
